﻿using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace FluentViewModel.Test
{
    [TestClass]
    public sealed class ViewModelBehavior
    {
        private IServiceLocator serviceLocator;

        [TestInitialize]
        public void InitializeTest()
        {
            serviceLocator = Configuration
                .Begin()
                    .Add<ViewModelControllerConfiguration>()
                    .Add<TransientServiceConfiguration>()
                    .Add<AddressViewModelConfiguration>()
                    .Add<CustomerViewModelConfiguration>()
                    .Add<PersonViewModelConfiguration>()
                .End();
        }

        [TestMethod]
        public void CanResolveViewModel()
        {
            var address = serviceLocator.Resolve<IAddressViewModel>();
            Assert.IsNotNull(address);
        }

        [TestMethod]
        public void ViewModelIsTransient()
        {
            var address1 = serviceLocator.Resolve<IAddressViewModel>();
            var address2 = serviceLocator.Resolve<IAddressViewModel>();
            address1.City = "Wow";
            Assert.AreNotSame(address1, address2);
        }

        [TestMethod]
        public void CanResolveController()
        {
            var controller = serviceLocator.Resolve<IViewModelController>();
            Assert.IsNotNull(controller);
        }

        [TestMethod]
        public void ControllerIsSingleton()
        {
            var controller1 = serviceLocator.Resolve<IViewModelController>();
            var controller2 = serviceLocator.Resolve<IViewModelController>();
            Assert.AreSame(controller1, controller2);
        }

        [TestMethod]
        public void ControllerIsTransient()
        {
            var controller1 = serviceLocator.Resolve<ISomeService>();
            var controller2 = serviceLocator.Resolve<ISomeService>();
            Assert.AreNotSame(controller1, controller2);
        }

        [TestMethod]
        public void ControllerDependency()
        {
            var address = serviceLocator.Resolve<IAddressViewModel>();
            var controller = serviceLocator.Resolve<IViewModelController>();
            controller.Test(address);
            Assert.AreNotEqual(0, address.TestCounter);
        }

        [TestMethod]
        public void NotifyPropertyChange()
        {
            var address = serviceLocator.Resolve<IAddressViewModel>();
            var addressViewModel = (ViewModel)address;
            var callCounter = 0;
            addressViewModel.PropertyChanged += (o, e) => ++callCounter;
            address.City = "Monkey";
            Assert.AreNotEqual(0, callCounter);
        }

        [TestMethod]
        public void DoesNotNotify()
        {
            var address = serviceLocator.Resolve<IAddressViewModel>();
            var addressViewModel = (ViewModel)address;
            var callCounter = 0;
            addressViewModel.PropertyChanged += (o, e) => ++callCounter;
            address.Country = "Monkey";
            Assert.AreEqual(0, callCounter);
        }

        [TestMethod]
        public void Initializers()
        {
            var address = serviceLocator.Resolve<IPersonViewModel>();
            Assert.IsNotNull(address.Address);
            Assert.IsNotNull(address.Family);
        }

        [TestMethod]
        public void ControllerInitialize()
        {
            var person = serviceLocator.Resolve<IPersonViewModel>();
            Assert.AreNotEqual(0, person.InitializeCounter);
        }

        [TestMethod]
        public void ControllerCommand()
        {
            var person = serviceLocator.Resolve<IPersonViewModel>();
            person.Save.Execute(null);
            Assert.AreNotEqual(0, person.CommandCounter);
        }

        [TestMethod]
        public void SingletonViewModel()
        {
            var customer1 = serviceLocator.Resolve<ICustomerViewModel>();
            var customer2 = serviceLocator.Resolve<ICustomerViewModel>();
            Assert.AreSame(customer1, customer2);
        }
    }
}